{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 矩阵\n",
    "\n",
    "## 什么是矩阵\n",
    "\n",
    "向量是对数的拓展, 一个向量表示一组数\n",
    "\n",
    "矩阵是对向量的拓展, 一个矩阵表示一组向量\n",
    "\n",
    "方阵 -- 行数=列数\n",
    "\n",
    "```python\n",
    "from vector import Vector\n",
    "\n",
    "class Matrix:\n",
    "\n",
    "    def __init__(self, list2d):\n",
    "        # 简写 self._values = [row[:] for row in lst2d]\n",
    "        self._values = [row[:] for row in list2d]\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f\"Matrix({self._values})\"\n",
    "\n",
    "    __str__ = __repr__\n",
    "\n",
    "\n",
    "\n",
    "    def row_num(self):\n",
    "        \"\"\"矩阵行数\"\"\"\n",
    "        return self.shape()[0]\n",
    "\n",
    "    __len__ = row_num\n",
    "\n",
    "    def col_num(self):\n",
    "        \"\"\"矩阵列数\"\"\"\n",
    "        return self.shape()[1]\n",
    "\n",
    "    def shape(self):\n",
    "        \"\"\"返回矩阵形状: 行数, 列数\"\"\"\n",
    "        return len(self._values), len(self._values[0])\n",
    "\n",
    "    def size(self):\n",
    "        \"\"\"矩阵元素个数\"\"\"\n",
    "        r, c = self.shape()\n",
    "        return r*c\n",
    "\n",
    "    def __getitem__(self, pos):\n",
    "        \"\"\"下标访问\"\"\"\n",
    "        r, c = pos\n",
    "        return self._values[r][c]\n",
    "\n",
    "    def row_vector(self,index):\n",
    "        \"\"\"返回矩阵第index个行向量\"\"\"\n",
    "        return Vector(self._values[index])\n",
    "\n",
    "    def col_vector(self,index):\n",
    "        \"\"\"返回矩阵第index个列向量\"\"\"\n",
    "        return Vector([row[index] for row in self._values])\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    m = Matrix([[1, 2], [3 ,4]])\n",
    "    print(m.shape())\n",
    "    print(m.size())\n",
    "    print(len(m))\n",
    "    print(m[1,0])\n",
    "    print(m.row_vector(1))\n",
    "    print(m.col_vector(1))\n",
    "```\n",
    "\n",
    "## 矩阵的基本运算\n",
    "\n",
    "1. 矩阵的加法\n",
    "2. 矩阵的数量乘法\n",
    "\n",
    "```python\n",
    "def __add__(self, other):\n",
    "    \"\"\"矩阵加法\"\"\"\n",
    "    assert self.shape() == other.shape(), \"Error in add,Vector shape must be same\"\n",
    "    return Matrix([[a + b for a, b in zip(self.row_vector(i), other.row_vector(i))] for i in range(self.row_num())])\n",
    "\n",
    "def __sub__(self, other):\n",
    "    \"\"\"矩阵减法\"\"\"\n",
    "    assert self.shape() == other.shape(), \"Error in sub,Vector shape must be same\"\n",
    "    return Matrix([[a - b for a, b in zip(self.row_vector(i), other.row_vector(i))] for i in range(self.row_num())])\n",
    "\n",
    "def __mul__(self, k):\n",
    "    \"\"\"数乘\"\"\"\n",
    "    return Matrix([[e*k for e in self.row_vector(i)] for i in range(self.row_num())])\n",
    "\n",
    "def __rmul__(self, k):\n",
    "    \"\"\"数乘\"\"\"\n",
    "    return Matrix([[e*k for e in self.row_vector(i)] for i in range(self.row_num())])\n",
    "\n",
    "def __truediv__(self, k):\n",
    "    \"\"\"矩阵数除\"\"\"\n",
    "    return self * (1/k)\n",
    "\n",
    "def __pos__(self):\n",
    "    \"\"\"+正号处理\"\"\"\n",
    "    return 1 * self\n",
    "\n",
    "def __neg__(self):\n",
    "    \"\"\"-负号处理\"\"\"\n",
    "    return -1 * self\n",
    "\n",
    "@classmethod\n",
    "def zero(cls,r,c):\n",
    "    \"\"\"创建0矩阵\"\"\"\n",
    "    return Matrix([[0]*c for _ in range(r)])\n",
    "\n",
    "@classmethod\n",
    "def one(cls,r,c):\n",
    "    \"\"\"创建1矩阵\"\"\"\n",
    "    return Matrix([[1]*c for _ in range(r)])\n",
    "```\n",
    "\n",
    "## 矩阵的基本运算性质\n",
    "\n",
    "1. 交换律: A+B=B+A\n",
    "2. 结合律: (A+B)+C=A+(B+C)\n",
    "3. 存在矩阵O,满足: A+O=A\n",
    "4. 存在矩阵-A:满足: A+(-A)=O,且-A唯一:-A=(-1)A\n",
    "5. (ck)A=c(kA)\n",
    "6. k(A+B)=kA+kB\n",
    "7. (c+k)A=cA+kA\n",
    "\n",
    "## 看待矩阵的另一个视角：系统\n",
    "\n",
    "### 矩阵和向量的乘法\n",
    "\n",
    "![9d40a1ec3356052b76950c80abe9e942.png](:/5e7437db9c534b6a8f0dbd32bb402e5f)\n",
    "\n",
    "![223cc15dc171eb7b03326b7c8f475af3.png](:/8b64778b65e94e0b8e343ea652893ebf)\n",
    "\n",
    "$T\\cdot\\vec{a}=\\vec{b}$\n",
    "矩阵T实际上将向量a转换为向量b!!!可以把矩阵理解为向量的函数\n",
    "\n",
    "\n",
    "### 矩阵和矩阵的乘法\n",
    "\n",
    "![01555b41abed564644b8b2c39f58a6eb.png](:/ef4681cc13dd4c13ab315ef835fc0e8b)\n",
    "\n",
    "不遵守交换律 -- $AB \\neq BA$\n",
    "\n",
    "```python\n",
    "def dot(self, other):\n",
    "    if isinstance(other, Vector):\n",
    "        # 矩阵和向量的乘法\n",
    "        assert self.col_num() == len(other), \"Error in dot, vector length must be same matrix col_num\"\n",
    "        # return Vector([sum(v[i] * other[i] for i in range(len(other))) for v in self._values])\n",
    "        return Vector([self.row_vector(i).dot(other) for i in range(self.row_num())])\n",
    "    if isinstance(other, Matrix):\n",
    "        # 矩阵,矩阵乘法\n",
    "        assert self.col_num() == other.row_num(), \\\n",
    "            \"Error in dot, matrix a col num {} must be same matrix B row_num {}\".format(self.col_num(),other.row_num())\n",
    "        return Matrix([ [ self.row_vector(i).dot(other.col_vector(j)) for j in range(other.col_num())] for i in range(self.row_num())])\n",
    "\n",
    "```\n",
    "\n",
    "## 矩阵乘法的性质和矩阵的幂\n",
    "\n",
    "矩阵乘法不遵守交换律: $AB \\neq BA$\n",
    "\n",
    "矩阵乘法遵守:\n",
    "\n",
    "- (AB)C = A(BC)\n",
    "- A(B+c) = AB + AC\n",
    "- (B+C)A =BA + CA\n",
    "- 任意$A_r*c$,存在$O_c*k$, 使得 AO=O\n",
    "\n",
    "矩阵的幂\n",
    "\n",
    "1. $A^k = \\underbrace{A\\cdot A\\cdot A....\\cdot A}_k$\n",
    "2. 必须是方阵\n",
    "3. $(A+B)^2=A^2+AB+BA+B^2$\n",
    "\n",
    "## 矩阵的转置\n",
    "\n",
    "转置的性质\n",
    "\n",
    "1. $(A^T)^T = A$\n",
    "2. $(A+B)^T = A^T+B^T$\n",
    "3. $(k\\cdot A)^T=kA^T$\n",
    "4. $(A\\cdot B)^T = B^T \\cdot A^T$\n",
    "\n",
    "```python\n",
    "def T(self):\n",
    "    \"\"\"矩阵转置\"\"\"\n",
    "    return Matrix([[e for e in self.col_vector(i)] for i in range(self.col_num())])\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
      "1 10\n",
      "2 20\n",
      "3 30\n",
      "140\n",
      "[10, 20, 30]\n",
      "1 10\n",
      "2 20\n",
      "3 30\n",
      "4 10\n",
      "5 20\n",
      "6 30\n",
      "7 10\n",
      "8 20\n",
      "9 30\n",
      "[140, 320, 500]\n",
      "[140, 320, 500]\n"
     ]
    }
   ],
   "source": [
    "# from vector import Vector\n",
    "from LinearAlgorithm.vector import Vector\n",
    "\n",
    "\n",
    "class Matrix:\n",
    "\n",
    "    def __init__(self, lst2d):\n",
    "        self._values = [[e for e in row] for row in lst2d]\n",
    "        # 简写 self._values = [row[:] for row in lst2d]\n",
    "\n",
    "    def __repr__(self):\n",
    "        return F\"Matrix({self._values})\"\n",
    "\n",
    "    __str__ = __repr__\n",
    "\n",
    "    def row_num(self):\n",
    "        return len(self._values)\n",
    "\n",
    "    def col_num(self):\n",
    "        return len(self._values[0])\n",
    "\n",
    "    def shape(self):\n",
    "        return len(self._values), len(self._values[0])\n",
    "\n",
    "    def size(self):\n",
    "        return self.row_num() * self.col_num()\n",
    "\n",
    "    def __getitem__(self, item):\n",
    "        r, c = item\n",
    "        return self._values[r][c]\n",
    "\n",
    "    def row_vector(self, index):\n",
    "        return Vector(self._values[index])\n",
    "\n",
    "    def col_vector(self, index):\n",
    "        return Vector([row[index] for row in self._values])\n",
    "\n",
    "    def __add__(self, other):\n",
    "        return Matrix([[a + b for a, b in zip(self.row_vector(i), other.row_vector(i))] for i in range(self.row_num())])\n",
    "\n",
    "    def __sub__(self, other):\n",
    "        return Matrix([[a - b for a, b in zip(self.row_vector(i), other.row_vector(i))] for i in range(self.row_num())])\n",
    "\n",
    "    def __mul__(self, k):\n",
    "        return Matrix([e * k for e in self.row_vector(i)] for i in range(self.row_num()))\n",
    "\n",
    "    def __rmul__(self, k):\n",
    "        return Matrix([e * k for e in self.row_vector(i)] for i in range(self.row_num()))\n",
    "\n",
    "    def __truediv__(self, k):\n",
    "        return self * (1 / k)\n",
    "\n",
    "    def __pos__(self):\n",
    "        return self * 1\n",
    "\n",
    "    def __neg__(self):\n",
    "        return self * -1\n",
    "\n",
    "    @classmethod\n",
    "    def ones(cls, r, c):\n",
    "        m = [[1] * c for _ in range(r)]\n",
    "        # for i in range(r):\n",
    "        #     for j in range(c):\n",
    "        #         if i == j:\n",
    "        #             m[i][j] = 1\n",
    "        return Matrix(m)\n",
    "\n",
    "    @classmethod\n",
    "    def zeros(cls, r, c):\n",
    "        m = [[0] * c for _ in range(r)]\n",
    "        return Matrix(m)\n",
    "\n",
    "    def T(self):\n",
    "        m._values = self._values\n",
    "        for i in range(self.row_num()):\n",
    "            for j in range(self.col_num()):\n",
    "                if i > j:\n",
    "                    m._values[i][j], m._values[j][i] = m._values[j][i], m._values[i][j]\n",
    "        return Matrix(m._values)\n",
    "\n",
    "    def dot(self, other):\n",
    "        if isinstance(other, Vector):\n",
    "            # 矩阵和向量的乘法\n",
    "            assert self.col_num() == len(other), \"Error in dot, vector length must be same matrix col_num\"\n",
    "            #return Vector([sum(v[i] * other[i] for i in range(len(other))) for v in self._values])\n",
    "            return Vector([self.row_vector(i).dot(other) for i in range(self.row_num())])\n",
    "\n",
    "    def dot1(self, other):\n",
    "        if isinstance(other, Vector):\n",
    "            # 矩阵和向量的乘法\n",
    "            assert self.col_num() == len(other), \"Error in dot, vector length must be same matrix col_num\"\n",
    "            return Vector([sum(v[i] * other[i] for i in range(len(other))) for v in self._values])\n",
    "            # return Vector([self.row_vector(i).dot(other) for i in range(self.row_num())])\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    m = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
    "    print(m)\n",
    "    # print(m.shape())\n",
    "    # print(m.col_num())\n",
    "    # print(m.row_num())\n",
    "    # print(m.size())\n",
    "    # print(m[1, 1])\n",
    "    # print(m.row_vector(1))\n",
    "    # print(m.col_vector(1))\n",
    "    # print(m + m)\n",
    "    # print(m * 3)\n",
    "    # print(Matrix.ones(5,5))\n",
    "    # print(m.T())\n",
    "    v1 = Vector([1, 2, 3])\n",
    "    v = Vector([10, 20, 30])\n",
    "    print(v1.dot(v))\n",
    "    print(v)\n",
    "    print(m.dot(v))\n",
    "    print(m.dot1(v))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
